<?php


namespace App\Imports;

use App\Exceptions\ApiException;
use App\Services\CommonService;
use App\Services\ProjectClassifyService;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithColumnLimit;
use Maatwebsite\Excel\Concerns\WithLimit;
use Maatwebsite\Excel\Concerns\WithStartRow;

/**
 * Class BookTitleImport
 * @package App\Imports
 * 适用于 29号文件
 */
class BookTitleImportLY implements ToModel, WithChunkReading, WithStartRow, WithColumnLimit, WithBatchInserts, WithLimit
{
    protected $partCompanyId;
    protected $chunkSize;
    protected $startRow;
    protected $endColumn;
    protected $batchSize;
    protected $baseArchivesNo;
    protected $bookTitleInstance;
    protected $importDetailKey;
    protected $projectClassifyRedisKey;
    protected $importDetail;
    protected $allImportArchiveNosRedisKey; //导入的案卷全部单位工程
    protected $canImportArchiveNosRedisKey; //有效导入的案卷涉及的单位工程

    public function __construct($partCompanyId, $importDetailKey)
    {
        $this->importDetailKey = $importDetailKey;
        $this->limit           = 8000; //只读取前8000行
        $this->chunkSize       = 100;  //将数据拆成小块读取
        $this->startRow        = 3;    //从第几行开始
        $this->endColumn       = 'N';  //指定到那一列为止
        $this->batchSize       = 100;  //批量写入的数据大小
        $this->partCompanyId   = $partCompanyId; //参建单位
        $this->allImportArchiveNosRedisKey    = $importDetailKey . ":AllImportArchiveNos";
        $this->canImportArchiveNosRedisKey    = $importDetailKey . ":CanImportArchiveNos";
    }

    /**
     * 导入数据
     */
    public function model(array $row)
    {
        $this->checkFormat($row); //第一步，核对格式

        $allImportArchiveNosRedisKey = $this->allImportArchiveNosRedisKey;
        $canImportArchiveNosRedisKey = $this->canImportArchiveNosRedisKey;

        if (is_numeric($row[0]) && trim($row[1])) { //is_numeric($row[0]) 因为中间可能会出现【路基】独自占领一行需排除
            $archivesNo = format_archives_no(trim($row[1]));
            $projectClassify = ProjectClassifyService::getProjectClassifyArrInfo($this->partCompanyId, $archivesNo, $allImportArchiveNosRedisKey, $canImportArchiveNosRedisKey);  //和项目分类数据进行比对，判断往哪个里面写入
            if ($projectClassify) { //案卷数据找到了匹配的单位工程
                $bookTitleInstance = CommonService::getBookTitleInstance($this->partCompanyId, $projectClassify['id']);
                $title   = format_str($row[2]);
                $dateRes = self::getStartEndDate($row[7]);
                $bookTitleInstance->updateOrCreate(
                    [ //查询条件
                        'part_company_id'     => $this->partCompanyId,  //项目分类目录
                        'project_classify_id' => $projectClassify['id'],
                        'archives_no'         => $archivesNo,
                    ],
                    [ //数据
                        'company_id'          => company_id(),          //所属公司
                        'serial_no'           => get_archives_serial_no($archivesNo),//序号
                        'title'               => $title,                //案卷题名
                        'word_material'       => to_int($row[3]),       //文字材料
                        'blueprint'           => to_int($row[4]),       //蓝图
                        'page_num'            => to_int($row[5]),       //总页数
                        'start_date'          => $dateRes[0],           //开始日期
                        'end_date'            => $dateRes[1],           //结束日期
                        'store_period'        => format_str($row[8]),   //保管期限
                        'remark'              => format_str($row[13]),  //备注
                        'created_at'          => now(),
                        'updated_at'          => now(),
                        'creator_id'          => user_id(),
                        'is_need_check'       => 1, //如果案卷进行了修改，要重新检查
                    ]);
                redis()->hincrby($this->importDetailKey, $projectClassify['title'], 1); //使用 redis()->hset(); //hash对指定的单位工程导入案卷数量数值进行加 操作
            }
        }
    }

    /**
     * 获取起止日期
     * 2009.04～2013.03
     * @param $startEndDate
     * @return array
     * @author: lxk
     * @date: 2024-10-22 15:48
     */
    public static function getStartEndDate($startEndDate) : array
    {
        if (empty($startEndDate) || strlen($startEndDate) != 17 || !str_contains($startEndDate, '～') || strpos($startEndDate, '～') != 7) {
            return ['', ''];
        }
        $startDate = substr($startEndDate, 0, 7);
        $endDate   = substr($startEndDate, -7, );

        return [$startDate, $endDate];
    }

    /**
     * 检查格式是否正确，判断列的属性汉字
     * @author: lxk
     * @date: 2023/6/3 15:18
     */
    public function checkFormat($row)
    {
        if (format_table_label($row[0]) == '序号') {
            if (
                (format_table_label($row[1]) != '档案号' && format_table_label($row[1]) != '档号')
                || !str_contains(format_table_label($row[2]), '案卷')
                || format_table_label($row[8]) != '保管期限'
            ) {
                throw new ApiException("案卷格式错误！列属性名必须和模板完全一致，请下载模板，核对数据列【A~N】");
            }
        }
    }

    /**
     * 将数据拆成小块进行导入，减小内存占用
     *
     * @return int
     */
    public function chunkSize(): int
    {
        return $this->chunkSize;
    }

    /**
     * 直接过滤表头，第一块数据含表头
     *
     * @return int
     */
    public function startRow(): int
    {
        return $this->startRow;
    }

    /**
     * 指定到那一列为止，G代表读取到G列就不再读取
     *
     * @return string
     */
    public function endColumn(): string
    {
        return $this->endColumn;
    }

    /**
     * 批量写入的数据大小
     *
     * @return int
     */
    public function batchSize(): int
    {
        return $this->batchSize;
    }

    public function limit(): int
    {
        return $this->limit;
    }

}
